<template>
  <div>
    <!--    三级列表选择-->
    <Category :disabled="isAdd"></Category>

    <!--    三级列表属性的渲染-->
    <el-card
        shadow="always"
        :body-style="{ padding: '20px' }"
        style="margin-top: 30px"
        v-show="!isAdd"
    >
      <template #header>
        <el-button
            type="primary"
            size="default"
            icon="ele-Plus"
            @click="addAttr"
            :disabled="!categoryList3Id"
        >添加属性
        </el-button
        >
      </template>
      <!-- card body -->
      <el-table :data="attrList" border stripe>
        <el-table-column type="index" width="80" label="序号"/>
        <el-table-column label="属性名称" prop="attrName"></el-table-column>
        <el-table-column
            label="属性值名称列表"
            width="500"
            prop="attrValueList"
        >
          <template v-slot="{ row }">
            <el-tag
                style="margin-right: 5px"
                type="danger"
                size="small"
                effect="dark"
                v-for="item in row.attrValueList"
                :key="item.id"
            >{{ item.valueName }}
            </el-tag
            >
          </template>
        </el-table-column>
        <el-table-column label="操作">
          <template v-slot="{ row }">
            <el-button title="修改" type="warning" size="small" icon="ele-Edit" @click="fixAttrValue(row)"></el-button>
            <el-popconfirm title="确定删除?" @confirm="removeAttr(row.id)">
              <template #reference>
                <el-button title="删除" type="danger" size="small" icon="ele-Delete"></el-button>
              </template>
            </el-popconfirm>

          </template>
        </el-table-column>
      </el-table>
    </el-card>

    <!--    添加或者修改-->
    <el-card
        shadow="always"
        :body-style="{ padding: '20px' }"
        style="margin-top: 30px"
        v-show="isAdd"
    >
      <el-form label-width="80px" :inline="true">
        <el-form-item label="属性名">
          <el-input v-model="newAttr.attrName" size="small" clearable/>
        </el-form-item>
      </el-form>
      <div>
        <el-button type="primary" size="default" @click="addAttrValue" :disabled="!newAttr.attrName">添加属性值</el-button>
        <el-button type="default" size="default" @click="isAdd = false"
        >取消
        </el-button
        >
      </div>
      <el-table border stripe style="margin: 20px 0" :data="newAttr.attrValueList">
        <el-table-column type="index" width="80" label="序号"/>
        <el-table-column label="属性值名称">
          <template #default="{row,$index}">
            <!--            编辑模式-->
            <el-input size="small"
                      clearable
                      ref="inputEle"
                      v-if="row.isEdit"
                      v-model="row.valueName"
                      @blur="editBlur(row,$index)">

            </el-input>
            <!--            查看模式-->
            <span v-else @click="switchover(row)">{{ row.valueName }}</span>
          </template>
        </el-table-column>
        <el-table-column label="操作">
          <template #default="{row,$index}">
            <el-button type="danger" icon="ele-Delete" @click="removeAttrValue($index)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>
      <div>
        <el-button type="primary" size="default" @click="save"
                   :disabled="newAttr.attrName == '' || newAttr.attrValueList.length === 0"
        >保存
        </el-button>
        <el-button type="default" size="default" @click="isAdd = false"
        >返回
        </el-button>
      </div>
    </el-card>
  </div>
</template>

<script lang=ts>
import {defineComponent} from 'vue';

export default defineComponent({
  name: 'Attr',
});
</script>

<script setup lang=ts>
import useCategoryStore from '@/stores/category';
import {storeToRefs} from 'pinia';
import {ElMessage} from 'element-plus/es';
import {nextTick, ref, watch} from 'vue';
import type {attrItemType, attrListType, attrValueItemType} from '@/api/attr';
import {reqAddOrUpdateAttrInfoListAsync, reqAttrInfoListAsync, reqDeleteAttrAsync} from '@/api/attr';
import {cloneDeep} from "lodash";

// 获取store对象
const categoryStore = useCategoryStore()

// 获取 categoryStore 里面保存的三级列表的id
const {categoryList1Id, categoryList2Id, categoryList3Id} = storeToRefs(categoryStore);

// 三级列表清完回来的数据
const attrList = ref<attrListType>([])

// 获取三级列表全部选中后的数据
const getAttrList = async () => {
  const result = await reqAttrInfoListAsync(
      categoryList1Id.value as number,
      categoryList2Id.value as number,
      categoryList3Id.value as number
  );

  //对初始值进行赋值
  attrList.value = result;
}

//等到三级分类的第三级的id改变以后,初始化发送属性列表请求
watch(categoryList3Id, async (newVal) => {
  //因为初始化一级分类的时候,三级分类也会发生改变,变为null,但是此时不需要重新发送请求
  if (!newVal) {
    attrList.value = [];
    return;
  }

  //一旦3Id改变,则重新发送请求
  try {
    await getAttrList()
  } catch (e: any) {
    ElMessage.error(e.message);
  }
});

// 是否显示添加/修改属性的组件
const isAdd = ref(false)  // 默认不显示

// 收集需要添加的数据/修改的数据
const newAttr = ref<attrItemType>(
    {
      attrName: '',  // 收集的当前的平台属性名
      attrValueList: [],  // 收集的当前属性的属性值列表
      categoryId: categoryList3Id.value as number,  // 固定的当前的category3Id的值  因为我们只能在 3id下面添加
      categoryLevel: 3,  // 固定的3
    }
)

// 点击添加属性
const addAttr = () => {
  // 显示添加组件
  isAdd.value = true;

  // 恢复添加组件的格式  清除上一次添加完 残留的数据
  newAttr.value = {
    attrName: '',  // 收集的当前的平台属性名
    attrValueList: [],  // 收集的当前属性的属性值列表
    categoryId: categoryList3Id.value as number,  // 固定的当前的category3Id的值
    categoryLevel: 3,  // 固定的3
  };

}

// 点击的添加属性值的数据
const addAttrValue = () => {
  // 添加的属性值的固定格式
  const attrValueItem: attrValueItemType = {
    attrId: newAttr.value.id,     // 是固定的 当前所在属性的id(新增的时候,属性没有id,没有关系,将来添加到服务端就有了)
    valueName: '',   // 双向数据绑定了 可以收集到 属性值
    isEdit: true   //新增一个属性,代表当前是编辑模式(添加属性值的时候 input标签) 还是查看模式(修改属性值的时候 span标签) 并且两种模式可以相互切换
  }

  newAttr.value.attrValueList.push(attrValueItem)

  // 自动获取焦点
  nextTick(() => {  // 因为我们在操作DOM 当数据发生改变时 视图也会发生改变 渲染DOM的时候是异步的 所以我们需要使用nextTick
    inputEle.value.focus()
  })

}

// 点击修改 显示修改组件的数据
const fixAttrValue = (row: attrItemType) => {
  // 显示修改组件
  isAdd.value = true

  // 使用收集的当前需要修的数据  赋值给双向绑定的数据
  newAttr.value = cloneDeep(row)

  //回填数据之后,我们给每一个属性值对象添加一个isEdit属性,代表当前属性值是编辑模式还是查看模式
  newAttr.value.attrValueList.forEach((item) => {
    item.isEdit = false;
  });
}

// 当input 编辑模式 失焦的时候(手动输入将要添加的属性值的时候)
const editBlur = (row: attrValueItemType, index: number) => {
  // 变为查看模式
  row.isEdit = false

  // 当添加的属性值为空的时候  清除当前行
  if (row.valueName === '') newAttr.value.attrValueList.splice(index, 1)

  // 当添加的属性值是否重复
  const re = newAttr.value.attrValueList.some(item => {
    if (item !== row) {
      // 不让自己和自己比
      return item.valueName === row.valueName
    }
  })
  // 如果重复 删除当前添加的
  if (re) newAttr.value.attrValueList.splice(index, 1)
}

// 当点击span标签 查看模式 切换成 input 编辑模式
const switchover = (row: attrValueItemType) => {
  // 变为编辑模式
  row.isEdit = true;

  // 自动获取焦点
  nextTick(() => {  // 因为我们在操作DOM 当数据发生改变时 视图也会发生改变 渲染DOM的时候是异步的 所以我们需要使用nextTick
    inputEle.value.focus()
  })
}

// 获取input组件的 DOM元素  用于编辑模式和查看模式自动获取焦点
const inputEle = ref()

// 删除添加或者修改里面的属性值
const removeAttrValue = (index: number) => {
  newAttr.value.attrValueList.splice(index, 1)
}

// 保存修改的后属性和属性值 以及 添加的属性和属性值
const save = async () => {
  // 因为我们在真实的发送数据的数据里面 添加了一个 不需要的值(控制编辑模式还是查看模式) 发请求的时候不需要 所以需要剔除
  newAttr.value.attrValueList = newAttr.value.attrValueList.map(item => {
    delete item.isEdit
    return item
  })

  // 当需要添加的数据为空的时候 是不能发请求的 这种数据没有必要
  if (newAttr.value.attrName == '' || newAttr.value.attrValueList.length === 0) return ElMessage.error('属性名和属性值不能为空')

  // 发送请求
  try {
    if (newAttr.value.id) {  // 修改
      await reqAddOrUpdateAttrInfoListAsync(newAttr.value)
      ElMessage.success('修改成功')
    } else {  // 添加
      await reqAddOrUpdateAttrInfoListAsync(newAttr.value)
      ElMessage.success('添加成功')
    }
  } catch (e: any) {
    ElMessage.error(newAttr.value.id ? '修改失败' : '添加失败')
  }
  // 更新数据
  await getAttrList()

  // 显示三级列表的数据
  isAdd.value = false
}

// 发请求删除整个属性
const removeAttr = async (id: number) => {
  try {
    await reqDeleteAttrAsync(id)
    ElMessage.success('删除成功')
    // 更新数据
    await getAttrList()
  } catch (e: any) {
    ElMessage.error(e.message)
  }
}
</script>

<style scoped></style>
